﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using personalplaner.business.extensions;
using personalplaner.business.stamm;
using personalplaner.common.mvvm;
using personalplaner.common.mvvm.commands;
using personalplaner.common.mvvm.common;
using personalplaner.common.mvvm.mediator;
using personalplaner.gui.stamm.viewmodels.models;
using personalplaner.gui.stamm.views;
using personalplaner.servicemodel.dataaccess;
using personalplaner.gui.stamm.windows;
using personalplaner.gui.common;
using System.Text;
using personalplaner.business;
using personalplaner.business.enums;

namespace personalplaner.gui.stamm.viewmodels
{
    public class PersonalStammViewModel : BaseViewModel
	{
        public PersonalStammViewModel(DependencyObject parent)
            : base(parent)
        {
        }

		public override void Loaded()
		{
			var mw = GetService<IMainWindowDisplayContainer>();
			mw.IsWaitVisible = false;
		}

        #region Mediator Messages

        [MediatorMessageSink("UpdatePersonPensum", ParameterType = typeof(int))]
        public void UpdatePersonPensum(int prsId)
        {
            var da = GetService<IPensumDataAccess>();
            Model.Pensum = da.GetPensum(Model.SelectedPerson.PrsID);
        }

        [MediatorMessageSink("UpdatePersonAbteilung", ParameterType = typeof(int))]
        public void UpdatePersonAbteilung(int prsId)
        {
            var ada = GetService<IAbteilungDataAccess>();
            Model.Abteilungen = ada.GetPersonAbteilungen(Model.SelectedPerson.PrsID, true, false);
        }

        [MediatorMessageSink("UpdatePersonAnstellung", ParameterType = typeof(int))]
        public void UpdatePersonAnstellung(int prsId)
        {
            var ansda = GetService<IAnstellungDataAccess>();
            Model.Anstellung = ansda.GetPersonAnstellung(Model.SelectedPerson.PrsID);
        }

        [MediatorMessageSink("SettingsRefresh")]
        public void SettingsRefresh()
        {
            if (Personen == null)
                return;
            var da = GetService<IOptionsDataAccess>();

            bool showPrsId = da.ShowPrsId;
            var nameDisplay = da.NameDisplayOption;
            foreach (var prs in Personen)
            {
                prs.ShowPrsId = showPrsId;
                prs.NameDisplay = nameDisplay;
            }
        }

        #endregion

        #region Commands

        ICommand _okcommand;
        public ICommand OkCommand
        {
            get
            {
                if (_okcommand == null)
                    _okcommand = new RelayCommand(OnOkCommand);
                return _okcommand;
            }
        }

		private void OnOkCommand(object parameter)
		{
			var wnd = Parent as Window;
			if (wnd != null)
			{
				wnd.DialogResult = true;
				wnd.Close();
				return;
			}

			var mw = GetService<IMainWindowDisplayContainer>();
			mw.MoveToPreviousView();
		}

    	ICommand _cancelcommand;
        public ICommand CancelCommand
        {
            get
            {
                if (_cancelcommand == null)
                    _cancelcommand = new RelayCommand(OnCancelCommand);
                return _cancelcommand;
            }
        }

        private void OnCancelCommand(object parameter)
        {
        	var wnd = Parent as Window;
			if (wnd != null)
			{
				wnd.DialogResult = false;
				wnd.Close();
				return;
			}

			var mw = GetService<IMainWindowDisplayContainer>();
			mw.MoveToPreviousView();
        }

        ICommand _savecommand;
        public ICommand SaveCommand
        {
            get
            {
                if (_savecommand == null)
					_savecommand = new RelayCommand(OnSave, parameter => Model.SelectedPerson != null && Model.SelectedPerson.IsValid);
                return _savecommand;
            }
        }

		private void OnSave(object parameter)
		{
			if (Model.SelectedPerson == null || !Model.SelectedPerson.IsValid)
			{
				MessageBox.Show("Es wurden nicht alle Daten angegeben eingegeben.", "", MessageBoxButton.OK,
				                MessageBoxImage.Error);
				return;
			}

			if (!Model.SelectedPerson.IsNew)
			{
				//get the data access via the service locator.
				var da = GetService<IPersonDataAccess>();
				//update person
                da.UpdatePerson(Model.SelectedPerson/*, Model.Pensum.Von, Model.Pensum.Bis, Model.Anstellung != null ? Model.Anstellung.AnstellungID : 0*/);
				for (int i = 0; i < Personen.Count; i++)
				{
					if (Personen[i].PrsID == Model.SelectedPerson.PrsID)
					{
						Personen[i] = Model.SelectedPerson;
                        //Personen[i].ID = int.MaxValue;
						ActiveGridItem = Personen[i];
						break;
					}
				}
			}
			else
			{
				//get the data access via the service locator.
				var da = GetService<IPersonDataAccess>();
				//save new person
				Model.SelectedPerson.PrsID = da.SavePerson(Model.SelectedPerson, Model.Pensum.Von, Model.Pensum.Bis,
				                                           Model.Anstellung.AnstellungID);
				for (int i = 0; i < Personen.Count; i++)
				{
					if (Personen[i].PrsID == Model.SelectedPerson.PrsID)
					{
						Personen[i] = Model.SelectedPerson;
						Personen[i].ID = int.MaxValue;
						ActiveGridItem = Personen[i];
						break;
					}
				}
			}
		}

    	ICommand _newcommand;
        public ICommand NewCommand
        {
            get
            {
                if (_newcommand == null)
                    _newcommand = new RelayCommand(OnNew);
                return _newcommand;
            }
        }

        private void OnNew(object parameter)
        {
            var wnd = new AddPersonWizard();
            wnd.Owner = Window.GetWindow(Parent);
			if (wnd.ShowDialog() == false)
				return;

			var da = GetService<IPersonDataAccess>();
			var itm = da.GetPerson(wnd.PrsId);

			if (itm == null)
				return;

			Personen.Add(itm);
			ActiveGridItem = itm;
        }

		ICommand _deleteCommand;
		public ICommand DeleteCommand
		{
			get
			{
				if (_deleteCommand == null)
					_deleteCommand = new RelayCommand(OnDelete, param => Model.SelectedPerson != null && !Model.SelectedPerson.IsNew);
				return _deleteCommand;
			}
		}

		private void OnDelete(object parameter)
		{
            //var sb = new StringBuilder();
            //sb.AppendLine(string.Format("Sind Sie sicher dass Sie die Person: {0} {1} wirklich löschen möchten?", Model.SelectedPerson.Nachname, Model.SelectedPerson.Name));
            //sb.AppendLine();
            //sb.AppendLine("Achtung!");
            //sb.AppendLine("Es werden alle Referenzen und alle bereits eingeplanten Dienste und Pläne unwiederruflich gelöscht!");
            //sb.AppendLine();
            //sb.AppendLine("Falls Sie die Person nur deaktivieren möchten,");
            //sb.AppendLine("können Sie einfach das Pensum, über die Schaltfläche 'Pensum ändern', auf das gewünschte Datum kündigen.");

            //if (MessageBox.Show(sb.ToString(),"Person löschen?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.No)
            //    return;
            if (MessageBox.Show(string.Format(Properties.Resources.DeletePersonQuestionFormat, Model.SelectedPerson.Nachname, Model.SelectedPerson.Name), Properties.Resources.DeletePerson, MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.No)
                return;

			var da = GetService<IPersonDataAccess>();
			if (!da.DeletePerson(Model.SelectedPerson))
				return;

			_personen = null;
			RaisePropertyChanged("Personen");
		}


        ICommand _setanstellungcommand;
        public ICommand SetAnstellungCommand
        {
            get
            {
                if (_setanstellungcommand == null)
					_setanstellungcommand = new RelayCommand(OnSetAnstellung, parameter => Model.SelectedPerson != null && !Model.SelectedPerson.IsNew);
                return _setanstellungcommand;
            }
        }

        private void OnSetAnstellung(object parameter)
        {
			var wnd = new SetPersonAnstellung(Model.SelectedPerson.PrsID);
            wnd.Owner = Window.GetWindow(Parent);
            wnd.ShowDialog();

            var ansda = GetService<IAnstellungDataAccess>();
            Model.Anstellung = ansda.GetPersonAnstellung(Model.SelectedPerson.PrsID);
        }

        ICommand _setpensumcommand;
        public ICommand SetPensumCommand
        {
            get
            {
                if (_setpensumcommand == null)
					_setpensumcommand = new RelayCommand(OnSetPensum, parameter => Model.SelectedPerson != null && !Model.SelectedPerson.IsNew);
                return _setpensumcommand;
            }
        }

        private void OnSetPensum(object parameter)
        {
            //var wnd = new SetPersonPensum(Model.SelectedPerson.PrsID);
            //wnd.Owner = Window.GetWindow(Parent);
            //wnd.ShowDialog();

            var service = GetService<IMainWindowDisplayContainer>();
            var setPensum = new SetPersonPensum(Model.SelectedPerson.PrsID);
            service.AddSimpleContentItem(enDisplayItemType.SetPersonPensum, setPensum, true);


            int prsid = Model.SelectedPerson.PrsID;

            var pda = GetService<IPersonDataAccess>();
            var lst = pda.GetPersonen(showAll: ShowAllPersonen);
            if (lst != null)
                Personen = new ObservableCollection<Person>(lst);

            Model.SelectedPerson = (from p in Personen where p.PrsID == prsid select p).FirstOrDefault();

            if (Model.SelectedPerson != null && setPensum.PensumChanged && !setPensum.IsKuendigung)
            {
                MessageBox.Show(string.Format("Das Pensum von {0} {1} wurde geändert.\nBitte passen Sie das Pensum pro Team (Abteilung) an das neue Pensum an.", Model.SelectedPerson.Name, Model.SelectedPerson.Nachname),
                    "Pensum anpassen", MessageBoxButton.OK, MessageBoxImage.Information);

                OnSetAbteilung(null);
            }
        }

        ICommand _setabteilungcommand;
        public ICommand SetAbteilungCommand
        {
            get
            {
                if (_setabteilungcommand == null)
					_setabteilungcommand = new RelayCommand(OnSetAbteilung, p => Model.SelectedPerson != null && !Model.SelectedPerson.IsNew);
                return _setabteilungcommand;
            }
        }

        private void OnSetAbteilung(object parameter)
        {
            //var wnd = new SetPersonAbteilung(Model.SelectedPerson.PrsID);
            //wnd.Owner = Window.GetWindow(Parent);
            //wnd.ShowDialog();


            var service = GetService<IMainWindowDisplayContainer>();
            service.AddSimpleContentItem(enDisplayItemType.SetPersonAbteilung, new SetPersonAbteilung(Model.SelectedPerson.PrsID), true);

            var ada = GetService<IAbteilungDataAccess>();
            Model.Abteilungen = ada.GetPersonAbteilungen(Model.SelectedPerson.PrsID, true, false);
        }

        ICommand _hollidayCommand;
        public ICommand HollidayCommand
        {
            get
            {
                if (_hollidayCommand == null)
                    _hollidayCommand = new RelayCommand(OnHolliday, p => Model.SelectedPerson != null);
                return _hollidayCommand;
            }
        }

        private void OnHolliday(object param)
        {
            var service = GetService<IMainWindowDisplayContainer>();
            service.AddSimpleContentItem(enDisplayItemType.HolidayStamm, new HolidayStamm(Model.SelectedPerson.PrsID), true);
        }

        #endregion

        #region Properties

        PersonalStammModel _model;
        public PersonalStammModel Model
        {
            get
            {
                if (_model == null)
                    _model = new PersonalStammModel();
                return _model;
            }
        }

        IList<Person> _personen;
        public IList<Person> Personen
        {
            get
            {
                if (Designer.IsDesignMode)
					return new ObservableCollection<Person>();

                if (_personen == null)
                {
                    //get the data access via the service locator
                    var da = GetService<IPersonDataAccess>();
					var lst = da.GetPersonen(showAll: ShowAllPersonen);
					_personen = lst != null ? new ObservableCollection<Person>(lst) : new ObservableCollection<Person>();

                    PersonenDisplayView = CollectionViewSource.GetDefaultView(_personen);
                }
                return _personen;
            }
            set
            {
                _personen = value;
                RaisePropertyChanged("Personen");

                if (value != null)
                    PersonenDisplayView = CollectionViewSource.GetDefaultView(value);
            }
        }

        Person _activegriditem;
        public Person ActiveGridItem
        {
            get
            {
                return _activegriditem;
            }
            set
            {
                _activegriditem = value;
				RaisePropertyChanged("ActiveGridItem");

                if (value == null)
                    return;

				Model.SelectedPerson = value.Clone<Person>();

                var da = GetService<IPensumDataAccess>();
                Model.Pensum = da.GetPensum(value.PrsID);

                var ada = GetService<IAbteilungDataAccess>();
                Model.Abteilungen = ada.GetPersonAbteilungen(value.PrsID, true, false);

                var ansda = GetService<IAnstellungDataAccess>();
                Model.Anstellung = ansda.GetPersonAnstellung(value.PrsID);
            }
        }

        bool _showAllPersonen=false;
        public bool ShowAllPersonen
        {
            get
            {
                return _showAllPersonen;
            }
            set
            {
                _showAllPersonen = value;

                FilterString = "";

                _personen = null;
                RaisePropertyChanged("ShowAllPersonen");
                RaisePropertyChanged("Personen");
            }
        }

        #endregion

        #region Filter

        string _filterString;
        public string FilterString
        {
            get
            {
                return _filterString;
            }
            set
            {
                _filterString = value;
                RaisePropertyChanged("FilterString");

                RefreshFilter();
            }
        }

        #region Implementation

        public ICollectionView PersonenDisplayView { get; set; }

        IList<Person> _displayedItems;

        /// <summary>
        /// refreshes the filtering of the combobox according to the string in <see cref="FilterString"/>
        /// </summary>
        private void RefreshFilter()
        {
            var source = PersonenDisplayView;
            if (source != null)
            {
                _displayedItems = new List<Person>();
                
                // remove previous filters
                //if (source.Filter != null)
                //    source.Filter -= new Predicate<object>(Filter);

                source.Filter = new Predicate<object>(Filter);

                if (_displayedItems.Count > 0)
                    Model.SelectedPerson = _displayedItems[0];
            }
        }

        /// <summary>
        /// method that gets called by the predicate in the ICollectionView.Filter that filters the entries in the dropdown
        /// according to the string in <see cref="FilterString"/>
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool Filter(object obj)
        {
            // no filter is set
            if (string.IsNullOrEmpty(FilterString))
                return true;

            // get the value from the property out of the bound object
            var value = obj as Person;
            if (value == null)
                return false;

            if (string.IsNullOrEmpty(value.Name) && string.IsNullOrEmpty(value.Nachname))
                return false;

            bool isFiltered = false;

            //bool isFiltered = value.DienstName.IndexOf(FilterString, StringComparison.CurrentCultureIgnoreCase) >= 0;
            if (!string.IsNullOrEmpty(value.Name))
                isFiltered = value.Name.IndexOf(FilterString, StringComparison.CurrentCultureIgnoreCase) >= 0;
            if(!isFiltered && !string.IsNullOrEmpty(value.Nachname))
                isFiltered = value.Nachname.IndexOf(FilterString, StringComparison.CurrentCultureIgnoreCase) >= 0;

            if (isFiltered)
                _displayedItems.Add(value);

            return isFiltered;
        }

        #endregion

        #endregion
    }
}
